package com.md.api.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.md.api.entity.HttpResult;
import com.md.api.common.utils.IpUtil;
import com.md.api.common.utils.JsonUtil;
import com.md.api.common.utils.Md5Utils;
import com.md.api.common.utils.VerifyUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 *@Description:拦截处理请求过快
 *@Author: zhangyi
 *@date: 2020/5/9 12:06
 */
@Aspect
@Component
public class DuplicateReqInterceptor {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Around(value = "@annotation(com.md.api.config.DuplicateReq)")
    public Object around(ProceedingJoinPoint joinPoint) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        //获取注解中传入的值
        DuplicateReq duplicateReq = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(DuplicateReq.class);
        long expire = duplicateReq.expire();
        String returnMsg = duplicateReq.returnMsg();
        String value = duplicateReq.clazz().getName();
        String key = null;

        //获取该切面环绕的方法的形参
        Object[] args = joinPoint.getArgs();
        try {
            //没有参数不拦截
            if (args == null) {
                return joinPoint.proceed();
            }

            String json = "";
            for (Object arg : args) {
                String name = arg.getClass().getName();
                //如果形参中的类型，和注解中传入的值，一样，则该对象的数据需要校验
                if (name.equals(value)) {
                    json = JsonUtil.toJSONString(arg);
                }
            }
            //请求参数为空，不需要校验，直接调用方法执行
            if (VerifyUtil.isMiss(json)) {
                return joinPoint.proceed();
            }

            String ipAddr = IpUtil.getRealIp(request);
            String requestURI = request.getRequestURI();
            //ip,url,param，拼接形成一个key,转MD5
            key = Md5Utils.encode(ipAddr + requestURI + json);
            boolean lock = false;
            lock = redisTemplate.opsForValue().setIfAbsent(key, "1");
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
            if (!lock) {
                return HttpResult.fail(returnMsg);
            }
            Object proceed = joinPoint.proceed();
            String parse = JSON.toJSONString(proceed, SerializerFeature.WriteMapNullValue, SerializerFeature.QuoteFieldNames, SerializerFeature.QuoteFieldNames);
            HttpResult result = JSONObject.parseObject(parse, HttpResult.class);
            if (result.getCode() != 200) {
                redisTemplate.delete(key);
            }
            return proceed;
        } catch (Throwable e) {
            logger.error("DuplicateReqInterceptor happen error:{}", e);
            if (!VerifyUtil.isMiss(key)) {
                redisTemplate.delete(key);
            }
            return HttpResult.fail(returnMsg);
        }
    }

}
